module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output shift_ena,
    output counting,
    input done_counting,
    output done,
    input ack );

    localparam FSM_W  = 8;
    localparam FSM_W1 = FSM_W - 1'b1;

    reg [FSM_W1:0]   state;
    reg [FSM_W1:0]   nxt_state;

    localparam  IDLE        = 0;
    localparam  S_0         = 1;
    localparam  S_1         = 2;
    localparam  S_11        = 3;
    localparam  S_110       = 4;
    localparam  S_SHFT_ENA  = 5;
    localparam  WAT_CNT_FIN = 6;
    localparam  WAT_ACK     = 7;

    reg [1:0]       asrt_cntr;
    wire            asrt_cntr_add;  
    wire            asrt_cntr_clr;  

    //assert signal cntr
    always @(posedge clk) begin
        if(reset) begin
            asrt_cntr              <= 'b0;
        end else if(asrt_cntr_add)begin
            asrt_cntr              <= asrt_cntr + 1'b1;
        end else if(asrt_cntr_clr)begin
            asrt_cntr              <= 'b0;
        end
    end
    assign                  asrt_cntr_add  = state[S_SHFT_ENA];
    assign                  asrt_cntr_clr  = 1'b0; // cntr clear itself

    // State transition logic (combinational)
    always @(*) begin
        nxt_state[IDLE   ]          =   1'b0; // never reach for nxt_state
        nxt_state[S_0    ]          =   (state[IDLE   ] && ~data) || (state[S_1    ] && ~data) || (state[S_0    ] && ~data) || (state[S_110   ] && ~data) || (state[WAT_ACK       ] && ack);
        nxt_state[S_1    ]          =   (state[IDLE   ] &&  data) || (state[S_0    ] &&  data);
        nxt_state[S_11   ]          =   (state[S_1    ] &&  data) || (state[S_11   ] &&  data);
        nxt_state[S_110  ]          =   (state[S_11   ] && ~data);
        nxt_state[S_SHFT_ENA ]      =   (state[S_110  ] &&  data) || (state[S_SHFT_ENA  ] && ~(asrt_cntr == 2'd3));

        nxt_state[WAT_CNT_FIN   ]   =   (state[S_SHFT_ENA] && asrt_cntr == 2'd3)
                                    || (state[WAT_CNT_FIN   ] && ~done_counting);

        nxt_state[WAT_ACK       ]   =   (state[WAT_CNT_FIN   ] && done_counting) 
        || (state[WAT_ACK       ] && ~ack);
    end

    // State flip-flops (sequential)
    always @(posedge clk) begin
        if(reset)
            state   <=  'b10; //SEQ_RCGN
        else begin
            state   <=  nxt_state;
        end  
    end

    //output logic
    assign  done        =   state[WAT_ACK] ;
    assign  counting    =   state[WAT_CNT_FIN];
    assign  shift_ena   =   state[S_SHFT_ENA];

endmodule
